﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AutoMapper;
using DTcms.Core.API.Filters;
using DTcms.Core.Common.Emum;
using DTcms.Core.Common.Extensions;
using DTcms.Core.Common.Helper;
using DTcms.Core.IServices;
using DTcms.Core.Model.Models;
using DTcms.Core.Model.ViewModels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;

namespace DTcms.Core.API.Controllers
{
    [Route("[controller]")]
    [ApiController]
    public class ArticleController : ControllerBase
    {
        private readonly ISiteService _siteService;
        private readonly ISiteChannelService _siteChannelService;
        private readonly IArticleService _articleService;
        private readonly IUserService _userService;
        private readonly IArticleLikeService _likeService;
        private readonly IArticleLabelService _labelService;
        private readonly IArticleCategoryService _categoryService;
        private readonly IMapper _mapper;

        public ArticleController(IArticleService articlesService,
            IUserService userService,
            ISiteService siteService,
            IArticleLikeService likeService,
            ISiteChannelService siteChannelService,
            IArticleLabelService labelService,
            IArticleCategoryService categoryService,
            IMapper mapper)
        {
            _articleService = articlesService;
            _userService = userService;
            _mapper = mapper;
            _siteChannelService = siteChannelService;
            _siteService = siteService;
            _likeService = likeService;
            _labelService = labelService;
            _categoryService = categoryService;
        }

        /// <summary>
        /// 根据ID获取数据
        /// 示例：/article/1/1
        /// </summary>
        [HttpGet("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.View, "channelId")]
        public async Task<IActionResult> GetById([FromRoute] long id, [FromQuery] BaseParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //查询数据库获取实体
            var model = await _articleService.QueryAsync(x => x.Id == id);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            //使用AutoMapper转换成ViewModel，根据字段进行塑形
            var result = _mapper.Map<ArticlesEditDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 获取指定数量列表
        /// 示例：/article/view/1/10
        /// </summary>
        [HttpGet("view/{channelId}/{top}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.View, "channelId")]
        public async Task<IActionResult> GetList([FromRoute] int channelId, [FromRoute] int top, [FromQuery] BaseParameter searchParam)
        {
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据库列表
            var resultFrom = await _articleService.QueryListAsync<Articles>(top,
                x => x.ChannelId.Equals(channelId) &&
                (!searchParam.Keyword.IsNotNullOrEmpty() || x.Title.Contains(searchParam.Keyword)),
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "SortId,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticlesDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }

        /// <summary>
        /// 获取分页列表
        /// 示例：/article/1?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("{channelId}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.View, "channelId")]
        public async Task<IActionResult> GetList([FromQuery] ArticleParameter searchParam, [FromQuery] PageParamater pageParam, [FromRoute] int channelId)
        {
            if (channelId <= 0)
            {
                return BadRequest(ResponseMessage.Error("请输入正确的参数"));
            }
            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据列表，如果ID大于0则查询该用户下所有的列表
            var list = await _articleService.QueryPageAsync(pageParam.PageSize,
                pageParam.PageIndex,
                x => x.ChannelId == channelId
                && (!searchParam.Keyword.IsNotNullOrEmpty() || x.Title.Contains(searchParam.Keyword))
                && (searchParam.CategoryId <= 0 || x.ArticleCategoryRelations.Any(x => x.CategoryId == searchParam.CategoryId))
                && (searchParam.LabelId <= 0 || x.ArticleLabelRelations.Any(x => x.LabelId == searchParam.LabelId))
                && (searchParam.StartDate == null || DateTime.Compare(x.AddTime, searchParam.StartDate.GetValueOrDefault()) >= 0)
                && (searchParam.EndDate == null || DateTime.Compare(x.AddTime, searchParam.EndDate.GetValueOrDefault()) <= 0),
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "SortId,-Id"
                );
            if (list == null || list.Count() <= 0)
            {
                return NotFound(ResponseMessage.Error("暂无查询到记录"));
            }

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticlesDto>>(list).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }

        /// <summary>
        /// 添加一条记录
        /// 示例：/article/1
        /// </summary>
        [HttpPost("{channelId}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.Add, "channelId")]
        public async Task<IActionResult> Add([FromBody] ArticlesAddDto modelDto)
        {
            //验证数据是否合法
            if (!TryValidateModel(modelDto))
            {
                return ValidationProblem(ModelState);
            }
            //获取当前用户名
            modelDto.AddBy = await _userService.GetUserNameAsync();
            modelDto.AddTime = DateTime.Now;
            //映射成实体
            var dtoModel = _mapper.Map<Articles>(modelDto);
            //检查频道是否存在
            if (!await _siteChannelService.ExistsAsync<SiteChannel>(x => x.Id == dtoModel.ChannelId))
            {
                return NotFound(ResponseMessage.Error($"频道{dtoModel.ChannelId}不存在或已删除"));
            }
            var channelModel = await _siteChannelService.QueryAsync(t => t.Id.Equals(dtoModel.ChannelId));
            //添加站点主键
            dtoModel.SiteId = channelModel.SiteId;
            //检查站点是否存在
            if (!await _siteService.ExistsAsync<Sites>(x => x.Id == dtoModel.SiteId))
            {
                return NotFound(ResponseMessage.Error($"站点{dtoModel.SiteId}不存在或已删除"));
            }
            //内容摘要提取内容前255个字符
            if (string.IsNullOrWhiteSpace(dtoModel.Zhaiyao) && !string.IsNullOrWhiteSpace(dtoModel.Content))
            {
                dtoModel.Zhaiyao = HtmlHelper.CutString(dtoModel.Content, 250);
            }

            //写入数据库
            var mapModel = await _articleService.AddAsync(dtoModel);
            //映射成DTO再返回，否则出错
            var result = _mapper.Map<ArticlesDto>(mapModel);
            return Ok(result);
        }

        /// <summary>
        /// 修改一条记录
        /// 示例：/article/1/15
        /// </summary>
        [HttpPut("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.Edit, "channelId")]
        public async Task<IActionResult> Update([FromRoute] long id, [FromBody] ArticlesEditDto modelDto)
        {
            //验证数据是否合法
            if (!TryValidateModel(modelDto))
            {
                return ValidationProblem(ModelState);
            }
            //内容摘要提取内容前255个字符
            if (string.IsNullOrWhiteSpace(modelDto.Zhaiyao) && !string.IsNullOrWhiteSpace(modelDto.Content))
            {
                modelDto.Zhaiyao = HtmlHelper.CutString(modelDto.Content, 250);
            }
            var result = await _articleService.UpdateAsync(id, modelDto);
            return NoContent();
        }

        /// <summary>
        /// 局部更新一条记录
        /// 示例：/article/1/1
        /// Body：[{"op":"replace","path":"/title","value":"new title"}]
        /// </summary>
        [HttpPatch("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.Edit, "channelId")]
        public async Task<IActionResult> Update([FromRoute] long id, [FromBody] JsonPatchDocument<ArticlesEditDto> patchDocument)
        {
            //注意：要使用写的数据库进行查询，才能正确写入数据主库
            var model = await _articleService.QueryAsync<Articles>(x => x.Id == id, WriteRoRead.Write);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }

            var modelToPatch = _mapper.Map<ArticlesEditDto>(model);
            patchDocument.ApplyTo(modelToPatch, ModelState);
            //验证数据是否合法
            if (!TryValidateModel(modelToPatch))
            {
                return ValidationProblem(ModelState);
            }
            //更新操作AutoMapper替我们完成，只需要调用保存即可
            _mapper.Map(modelToPatch, model);
            await _articleService.SaveAsync();

            return NoContent();
        }

        /// <summary>
        /// 批量审核记录
        /// 示例：/article/1?ids=1,2,3
        /// </summary>
        [HttpPut("{channelId}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.Audit)]
        public async Task<IActionResult> AuditByIds([FromQuery] string Ids)
        {
            if (Ids == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不可为空"));
            }
            //将ID列表转换成IEnumerable
            var arrIds = Ids.ToIEnumerable<long>();
            if (arrIds == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不符合规范"));
            }
            //找出符合条件的记录
            var list = await _articleService.QueryListAsync<Articles>(1000, x => x.Status == 1 && arrIds.Contains(x.Id), WriteRoRead.Write);
            if (list == null || list.Count() == 0)
            {
                return BadRequest(ResponseMessage.Error("没有找到需要审核的记录"));
            }
            foreach (var item in list)
            {
                item.Status = 0;
            }
            //保存到数据库
            await _articleService.SaveAsync();

            return NoContent();
        }

        /// <summary>
        /// 删除一条记录
        /// 示例：/article/1/1
        /// </summary>
        [HttpDelete("{channelId}/{id}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.Delete, "channelId")]
        public async Task<IActionResult> Delete([FromRoute] long id)
        {
            if (!await _articleService.ExistsAsync<Articles>(x => x.Id == id))
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            var result = await _articleService.DeleteAsync<Articles>(x => x.Id == id);

            return NoContent();
        }

        /// <summary>
        /// 批量删除记录(级联数据)
        /// 示例：/article/1?ids=1,2,3
        /// </summary>
        [HttpDelete("{channelId}")]
        [Authorize]
        [AuthorizeFilter("Article", ActionType.Delete, "channelId")]
        public async Task<IActionResult> DeleteByIds([FromQuery] string Ids)
        {
            if (Ids == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不可为空"));
            }
            //将ID列表转换成IEnumerable
            var arrIds = Ids.ToIEnumerable<long>();
            if (arrIds == null)
            {
                return BadRequest(ResponseMessage.Error("传输参数不符合规范"));
            }
            //执行批量删除操作
            await _articleService.DeleteAsync<Articles>(x => arrIds.Contains(x.Id));

            return NoContent();
        }

        /// <summary>
        /// 获取总记录数量
        /// 示例：/article/view/count
        /// </summary>
        [HttpGet("view/count")]
        [Authorize]
        public async Task<IActionResult> GetCount([FromQuery] ArticleParameter searchParam)
        {
            var result = await _articleService.QueryCountAsync(
                x => (searchParam.Status <= 0 || x.Status == searchParam.Status));
            //返回成功200
            return Ok(result);
        }

        #region 前台调用接口============================

        #region 根据文章主键获取指定数量列表
        /// <summary>
        /// 根据文章主键获取指定数量列表
        /// 示例：/client/article/view/1/10
        /// </summary>
        [HttpGet("/client/article/view/{id}/{top}")]
        public async Task<IActionResult> ClientGetList([FromRoute] int id, [FromRoute] int top, [FromQuery] ArticleParameter searchParam)
        {
            searchParam.Fields = "Id,SiteId,ChannelId,CallIndex,Title,Source,Author," +
                "LinkUrl,ImgUrl,SeoTitle,SeoKeyword,SeoDescription,Zhaiyao," +
                "Content,SortId,Click,Status,IsComment,CommentCount,LikeCount,AddTime,CategoryTitle," +
                "LabelTitle,ArticleFields,ArticleAlbums,ArticleAttachs,ArticleLabelRelations,ArticleCategoryRelations";

            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //获取文章实体
            var model = await _articleService.QueryAsync(x => x.Id == id);
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{id}不存在或已删除"));
            }
            List<long> categorys = new List<long>();
            categorys = model.ArticleCategoryRelations.Select(a => a.CategoryId).ToList();
            //获取数据库列表
            var resultFrom = await _articleService.QueryListAsync(top,
                x => x.ArticleCategoryRelations.Any(t => categorys.Contains(t.CategoryId))//当前文章的分类
                && (searchParam.Keyword.IsNotNullOrEmpty() ? x.Title.Contains(searchParam.Keyword) : true)//搜索关键字
                && (searchParam.LabelId > 0 ? x.ArticleLabelRelations.Any(t => t.LabelId == searchParam.LabelId) : true)//标签搜索
                && (searchParam.StartDate != null ? DateTime.Compare(x.AddTime, searchParam.StartDate.GetValueOrDefault()) >= 0 : true)
                && (searchParam.EndDate != null ? DateTime.Compare(x.AddTime, searchParam.EndDate.GetValueOrDefault()) <= 0 : true)
                && x.Id != id,
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "SortId,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticlesClientDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }
        #endregion

        #region 根据频道名称获取指定数量列表
        /// <summary>
        /// 根据频道名称获取指定数量列表
        /// 示例：/client/article/view/channel/news/10?categoryId=1
        /// </summary>
        [HttpGet("/client/article/view/channel/{channelName}/{top}")]
        public async Task<IActionResult> ClientGetList([FromRoute] string channelName, [FromRoute] int top, [FromQuery] ArticleParameter searchParam)
        {
            searchParam.Fields = "Id,SiteId,ChannelId,CallIndex,Title,Source,Author," +
                "LinkUrl,ImgUrl,SeoTitle,SeoKeyword,SeoDescription,Zhaiyao," +
                "Content,SortId,Click,Status,IsComment,CommentCount,LikeCount,AddTime,CategoryTitle," +
                "LabelTitle,ArticleFields,ArticleAlbums,ArticleAttachs,ArticleLabelRelations,ArticleCategoryRelations";

            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            if (string.IsNullOrWhiteSpace(channelName))
            {
                return BadRequest(ResponseMessage.Error("请传入频道名称"));
            }
            //获得频道实体
            SiteChannel channelModel = await _siteChannelService.QueryAsync(t => t.Name.Equals(channelName) && t.SiteId.Equals(searchParam.SiteId));
            if (channelModel == null)
            {
                return BadRequest(ResponseMessage.Error("频道不存在"));
            }
            //获取数据库列表
            var resultFrom = await _articleService.QueryListAsync(top,
                x => (searchParam.CategoryId > 0 ? x.ArticleCategoryRelations.Any(t => t.CategoryId == searchParam.CategoryId) : true)//查询分类
                && (searchParam.Keyword.IsNotNullOrEmpty() ? x.Title.Contains(searchParam.Keyword) : true)//查询关键字
                && (searchParam.LabelId > 0 ? x.ArticleLabelRelations.Any(t => t.LabelId == searchParam.LabelId) : true)//标签搜索
                && (searchParam.StartDate != null ? DateTime.Compare(x.AddTime, searchParam.StartDate.GetValueOrDefault()) >= 0 : true)
                && (searchParam.EndDate != null ? DateTime.Compare(x.AddTime, searchParam.EndDate.GetValueOrDefault()) <= 0 : true)
                && x.ChannelId == channelModel.Id,//频道查询
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "SortId,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticlesClientDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }
        #endregion

        #region 根据频道名称获取指定数量列表
        /// <summary>
        /// 频道主键获取指定数量列表
        /// 示例：/client/channel/article/view/1/10?categoryId=1
        /// </summary>
        [HttpGet("/client/channel/article/view/{channelId}/{top}")]
        public async Task<IActionResult> ClientGetListByChannelId([FromRoute] int channelId, [FromRoute] int top, [FromQuery] ArticleParameter searchParam)
        {
            searchParam.Fields = "Id,SiteId,ChannelId,CallIndex,Title,Source,Author," +
                "LinkUrl,ImgUrl,SeoTitle,SeoKeyword,SeoDescription,Zhaiyao," +
                "Content,SortId,Click,Status,IsComment,CommentCount,LikeCount,AddTime,CategoryTitle," +
                "LabelTitle,ArticleFields,ArticleAlbums,ArticleAttachs,ArticleLabelRelations,ArticleCategoryRelations";

            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据库列表
            var resultFrom = await _articleService.QueryListAsync(top,
                x => (searchParam.CategoryId > 0 ? x.ArticleCategoryRelations.Any(t => t.CategoryId == searchParam.CategoryId) : true)//查询分类
                && (searchParam.Keyword.IsNotNullOrEmpty() ? x.Title.Contains(searchParam.Keyword) : true)//查询关键字
                && (searchParam.LabelId > 0 ? x.ArticleLabelRelations.Any(t => t.LabelId == searchParam.LabelId) : true)//标签搜索
                && (searchParam.StartDate != null ? DateTime.Compare(x.AddTime, searchParam.StartDate.GetValueOrDefault()) >= 0 : true)
                && (searchParam.EndDate != null ? DateTime.Compare(x.AddTime, searchParam.EndDate.GetValueOrDefault()) <= 0 : true)
                && x.ChannelId == channelId,//频道查询
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "SortId,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticlesClientDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }
        #endregion

        #region 根据频道名称获取分页列表
        /// <summary>
        /// 根据频道名称获取分页列表
        /// 示例：/client/news/article?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("/client/{channelName}/article")]
        public async Task<IActionResult> ClientGetList([FromRoute] string channelName, [FromQuery] ArticleParameter searchParam, [FromQuery] PageParamater pageParam)
        {
            searchParam.Fields = "Id,SiteId,ChannelId,CallIndex,Title,Source,Author," +
                "LinkUrl,ImgUrl,SeoTitle,SeoKeyword,SeoDescription,Zhaiyao," +
                "Content,SortId,Click,Status,IsComment,CommentCount,LikeCount,AddTime,CategoryTitle," +
                "LabelTitle,ArticleFields,ArticleAlbums,ArticleAttachs,ArticleLabelRelations,ArticleCategoryRelations";

            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            if (string.IsNullOrWhiteSpace(channelName))
            {
                return BadRequest(ResponseMessage.Error("请传入频道名称"));
            }
            //获得频道实体
            SiteChannel channelModel = await _siteChannelService.QueryAsync(t => t.Name.Equals(channelName) && t.SiteId.Equals(searchParam.SiteId));
            if (channelModel == null)
            {
                return BadRequest(ResponseMessage.Error("频道不存在"));
            }

            //获取数据列表，如果ID大于0则查询该用户下所有的列表
            var list = await _articleService.QueryPageAsync(pageParam.PageSize,
                pageParam.PageIndex,
                x => x.ChannelId == channelModel.Id
                && (searchParam.Keyword.IsNotNullOrEmpty() ? x.Title.Contains(searchParam.Keyword) : true)
                && (searchParam.CategoryId > 0 ? x.ArticleCategoryRelations.Any(x => x.CategoryId == searchParam.CategoryId) : true)
                && (searchParam.LabelId > 0 ? x.ArticleLabelRelations.Any(x => x.LabelId == searchParam.LabelId) : true)
                && (searchParam.StartDate != null ? DateTime.Compare(x.AddTime, searchParam.StartDate.GetValueOrDefault()) >= 0 : true)
                && (searchParam.EndDate != null ? DateTime.Compare(x.AddTime, searchParam.EndDate.GetValueOrDefault()) <= 0 : true),
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "SortId,-Id"
                );
            if (list == null || list.Count() <= 0)
            {
                return NotFound(ResponseMessage.Error("暂无查询到记录"));
            }

            //x-pagination
            var paginationMetadata = new
            {
                totalCount = list.TotalCount,
                pageSize = list.PageSize,
                pageIndex = list.PageIndex,
                totalPages = list.TotalPages
            };
            Response.Headers.Add("x-pagination", SerializeHelper.SerializeObject(paginationMetadata));

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticlesClientDto>>(list).ShapeData(searchParam.Fields);
            return Ok(resultDto);
        }
        #endregion

        #region 根据频道主键获取分页列表
        /// <summary>
        /// 根据频道主键获取分页列表
        /// 示例：/client/article/1?pageSize=10&pageIndex=1
        /// </summary>
        [HttpGet("/client/article/{channelId}")]
        public async Task<IActionResult> ClientGetList([FromRoute] int channelId, [FromQuery] ArticleParameter searchParam, [FromQuery] PageParamater pageParam)
        {
            searchParam.Fields = "Id,SiteId,ChannelId,CallIndex,Title,Source,Author," +
                "LinkUrl,ImgUrl,SeoTitle,SeoKeyword,SeoDescription,Zhaiyao," +
                "Content,SortId,Click,Status,IsComment,CommentCount,LikeCount,AddTime,CategoryTitle," +
                "LabelTitle,ArticleFields,ArticleAlbums,ArticleAttachs,ArticleLabelRelations,ArticleCategoryRelations";

            //检测参数是否合法
            if (searchParam.OrderBy.IsNotNullOrEmpty()
                && !searchParam.OrderBy.Replace("-", "").IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的排序参数"));
            }
            if (!searchParam.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }

            //获取数据库列表
            var resultFrom = await _articleService.QueryListAsync(0,
                x => x.ChannelId.Equals(channelId)
                && (searchParam.Keyword.IsNotNullOrEmpty() ? x.Title.Contains(searchParam.Keyword) : true)
                && (searchParam.CategoryId > 0 ? x.ArticleCategoryRelations.Any(x => x.CategoryId == searchParam.CategoryId) : true)
                && (searchParam.LabelId > 0 ? x.ArticleLabelRelations.Any(x => x.LabelId == searchParam.LabelId) : true)
                && (searchParam.StartDate != null ? DateTime.Compare(x.AddTime, searchParam.StartDate.GetValueOrDefault()) >= 0 : true)
                && (searchParam.EndDate != null ? DateTime.Compare(x.AddTime, searchParam.EndDate.GetValueOrDefault()) <= 0 : true),
                searchParam.OrderBy.IsNotNullOrWhiteSpace() ? searchParam.OrderBy : "SortId,-Id");

            //映射成DTO，根据字段进行塑形
            var resultDto = _mapper.Map<IEnumerable<ArticlesClientDto>>(resultFrom).ShapeData(searchParam.Fields);
            //返回成功200
            return Ok(resultDto);
        }
        #endregion

        /// <summary>
        /// 根据别名或ID获取数据
        /// 示例：/client/article/show/1
        /// </summary>
        [HttpGet("/client/article/show/{key}")]
        public async Task<IActionResult> ClientGetByKey([FromRoute] string key, [FromQuery] BaseParameter param)
        {
            //检测参数是否合法
            if (!param.Fields.IsPropertyExists<ArticlesDto>())
            {
                return BadRequest(ResponseMessage.Error("请输入正确的属性参数"));
            }
            //查询数据库获取实体
            Articles model = null;
            if (int.TryParse(key, out int articleId))
            {
                model = await _articleService.QueryAsync(x => x.Id == articleId && x.Status == 0);
            }
            if (model == null)
            {
                model = await _articleService.QueryAsync(
                    x => x.CallIndex.ToLower() == key.ToLower()
                    && x.Status == 0
                    && (param.SiteId <= 0 || x.SiteId == param.SiteId));
            }
            //查询数据库获取实体
            if (model == null)
            {
                return NotFound(ResponseMessage.Error($"数据{key}不存在或已删除"));
            }
            //浏览量加一
            model.Click++;
            await _articleService.UpdateClickAsync(model.Id, model.Click);
            //使用AutoMapper转换成ViewModel，根据字段进行塑形
            var result = _mapper.Map<ArticlesClientDto>(model).ShapeData(param.Fields);
            return Ok(result);
        }

        /// <summary>
        /// 更新点击量
        /// 示例：/client/article/1
        /// </summary>
        [HttpPut("/client/article/{id}")]
        public async Task<IActionResult> UpdateClick([FromRoute] long id)
        {
            long clickCount = 0;
            //查出原来的数据
            Articles oldArticleModel = await _articleService.QueryAsync(t => t.Id == id);
            //检测是否为空
            if (oldArticleModel != null)
            {
                clickCount = await _articleService.UpdateClickAsync(oldArticleModel.Id, oldArticleModel.Click + 1);
            }
            else
            {
                return BadRequest(ResponseMessage.Error("参数不正确"));
            }
            return Ok(clickCount);
        }

        /// <summary>
        /// 更新点赞量
        /// 示例：/client/article/like/1
        /// </summary>
        [Authorize]
        [HttpPut("/client/article/like/{articleId}")]
        public async Task<IActionResult> UpdateLike([FromRoute] long articleId)
        {
            long likeCount = 0;
            likeCount = await _likeService.UserUpdateLikeAsync(articleId);
            return Ok(likeCount);
        }

        /// <summary>
        /// 获得每个分类的前几条数据
        /// </summary>
        /// <returns></returns>
        [HttpGet("/client/article/view/{channel}/{categoryTop}/{arcitleTop}")]
        public async Task<IActionResult> GetList([FromRoute] string channel, [FromRoute] int categoryTop, [FromRoute] int arcitleTop, [FromQuery] BaseParameter param)
        {
            //用于存放查询到列表
            List<object> resultList = new List<object>();
            param.Fields = "Id,SiteId,ChannelId,CallIndex,Title,Source,Author," +
                "LinkUrl,ImgUrl,SeoTitle,SeoKeyword,SeoDescription,Zhaiyao," +
                "Content,SortId,Click,Status,IsComment,CommentCount,LikeCount,AddTime,CategoryTitle," +
                "LabelTitle,ArticleFields,ArticleAlbums,ArticleAttachs,ArticleLabelRelations,ArticleCategoryRelations";

            //获得频道实体
            var channelModel = await _siteChannelService.QueryAsync(x => x.Name == channel && x.SiteId == param.SiteId);
            if (channelModel == null)
            {
                return BadRequest(ResponseMessage.Error("频道不存在"));
            }

            //获得分类列表
            var categoryList = await _categoryService.QueryListAsync<ArticleCategory>(categoryTop, 
                x => x.ChannelId == channelModel.Id && x.ParentId == 0 && x.Status == 0, "SortId,Id");
            foreach (var item in categoryList)
            {
                var articleList = await _articleService.QueryListAsync(arcitleTop,
                    x => x.ChannelId == channelModel.Id
                    && x.ArticleCategoryRelations.Any(x => x.CategoryId == item.Id)
                    && (param.Keyword.IsNotNullOrEmpty() ? x.Title.Contains(param.Keyword) : true),
                    param.OrderBy.IsNotNullOrWhiteSpace() ? param.OrderBy : "SortId,-Id");
                //使用AutoMapper转换成ViewModel，根据字段进行塑形
                var result = _mapper.Map<IEnumerable<ArticlesClientDto>>(articleList).ShapeData(param.Fields);
                resultList.Add(
                    new
                    {
                        Id = item.Id,
                        Title = item.Title,
                        Data = result
                    }
               );
            }
            return Ok(resultList);
        }
        #endregion
    }
}
